package com.nexgo.payment.trans.setting;

import android.support.annotation.NonNull;
import android.text.TextUtils;

import com.nexgo.common.ByteUtils;
import com.nexgo.oaf.apiv3.SdkResult;
import com.nexgo.oaf.apiv3.device.pinpad.AlgorithmModeEnum;
import com.nexgo.oaf.apiv3.device.pinpad.PinPad;
import com.nexgo.payment.App;
import com.nexgo.payment.R;
import com.nexgo.payment.aop.annotation.RunOnMainThread;
import com.nexgo.payment.api.ApiDeviceEngine;
import com.nexgo.payment.constrant.PreferencesConstants;
import com.nexgo.payment.databases.DataSource;
import com.nexgo.payment.databases.PasswordInfo;
import com.nexgo.payment.util.EncryptUtils;
import com.nexgo.payment.util.StringUtils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Map;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * Created by xiaox on 2017/1/12.
 */

public class SaveParameterPresenter implements SaveParameterContract.Presenter {
    private Logger mLog = LoggerFactory.getLogger(SaveParameterPresenter.class.getSimpleName());

    private Map<String, String> mParamData;
    private final SaveParameterContract.View mView;
    private DataSource mRepository;

    public SaveParameterPresenter(@NonNull SaveParameterContract.View view, @NonNull DataSource repository) {
        mView = checkNotNull(view);
        mRepository = checkNotNull(repository);
        mView.setPresenter(this);
    }

    @Override
    public void start() {
        mView.showDetail();
    }

    @Override
    public void pause() {

    }

    @Override
    public void destroy() {

    }

    @Override
    public void saveParams(Map<String, String> paramData) {
        if (paramData == null) return;
        mParamData = paramData;
        //保存商户信息
        if (paramData.containsKey(PreferencesConstants.MERCHANT_ID)
                || paramData.containsKey(PreferencesConstants.TERMINAL_ID)) {
            // 先判断商户号和终端号的值是否变化了，没有变化直接退出
            if (judgeMerAndTerValueChanges()) {
                if (mRepository.getReversalTransRecordNum() > 0||mRepository.getSuccessfulTransRecordNum() > 0) {
                    postMainThread(() -> mView.showNeedSettle());
                } else {
                    postMainThread(() -> mView.showInputSecurityPassword());
                }
                return;
            }
        }
        //保存终端主密钥信息
        if (paramData.containsKey(PreferencesConstants.INPUT_MASTER_KEY_INDEX)
                || paramData.containsKey(PreferencesConstants.INPUT_MASTER_KEY_VALUE)) {
            saveMainKeyValue();
            return;
        }
        doSaveParams();
    }

    @Override
    public void judgeSecurityPassword(String password) {
        //获取安全密码
        String securityPassword = getPasswordInfo().getSecurityPassword();
        if (TextUtils.isEmpty(password) || password.length() != 8) {
            postMainThread(() -> mView.showTip(App.sContext.getString(R.string.security_password_error)));
            return;
        }
        if (TextUtils.isEmpty(securityPassword) || !securityPassword.equals(EncryptUtils.encryptSHA256ToString(password))) {
            postMainThread(() -> mView.showTip(App.sContext.getString(R.string.security_password_error)));
            return;
        }
        doSaveParams();
    }

    @Override
    public String getParamValue(String preferencesId) {
        return mRepository.getParamValue(preferencesId);
    }

    @Override
    public void setParamValue(String preferencesId, String value) {
        mRepository.setParamValue(preferencesId, value);
    }

    @Override
    public void syncParamValue() {
        mRepository.syncParamValue();
    }

    @Override
    public void clearVoucherRecord() {
        mRepository.clearTransRecord();
    }

    @Override
    public void clearReversalRecord() {
        mRepository.clearReversalRecord();
    }

    @Override
    public PasswordInfo getPasswordInfo() {
        return mRepository.getPasswordInfo();
    }

    @Override
    public void savePassword(String key, List<String> values) {
        PasswordInfo info = mRepository.getPasswordInfo();
        if (info == null || values == null || values.size() != 2) return;
        String oldPassword = values.get(0);
        String newPassword = values.get(1);
        mLog.debug("oldPassword = {}, newPassword = {}", oldPassword, newPassword);
        switch (key) {
            case PreferencesConstants.MANAGE_PASSWORD:
                if (TextUtils.isEmpty(oldPassword)) {
                    postMainThread(() -> mView.showTip(App.sContext.getString(R.string.org_manage_password_is_empty)));
                    return;
                }
                if (TextUtils.isEmpty(newPassword)) {
                    postMainThread(() -> mView.showTip(App.sContext.getString(R.string.manage_pwd_is_empty)));
                    return;
                }
                if (newPassword.length() != 8) {
                    postMainThread(() -> mView.showTip(App.sContext.getString(R.string.manage_pwd_length_err)));
                    return;
                }
                //判断原管理员密码是否正确
                if (!info.getManagePassword().equals(EncryptUtils.encryptSHA256ToString(oldPassword))) {
                    postMainThread(() -> mView.showTip(App.sContext.getString(R.string.org_manage_password_err)));
                    return;
                }
                info.setManagePassword(EncryptUtils.encryptSHA256ToString(newPassword));
                break;
            case PreferencesConstants.ADMIN_PASSWORD:
                if (TextUtils.isEmpty(oldPassword)) {
                    postMainThread(() -> mView.showTip(App.sContext.getString(R.string.org_admin_password_is_empty)));
                    return;
                }
                if (TextUtils.isEmpty(newPassword)) {
                    postMainThread(() -> mView.showTip(App.sContext.getString(R.string.charge_pwd_is_empty)));
                    return;
                }
                if (newPassword.length() != 6) {
                    postMainThread(() -> mView.showTip(App.sContext.getString(R.string.charge_pwd_length_err)));
                    return;
                }
                //判断原主管密码是否正确
                if (!info.getAdminPassword().equals(EncryptUtils.encryptSHA256ToString(oldPassword))) {
                    postMainThread(() -> mView.showTip(App.sContext.getString(R.string.org_admin_password_err)));
                    return;
                }
                info.setAdminPassword(EncryptUtils.encryptSHA256ToString(newPassword));
                break;
            case PreferencesConstants.SECURITY_PASSWORD:
                if (TextUtils.isEmpty(oldPassword)) {
                    postMainThread(() -> mView.showTip(App.sContext.getString(R.string.org_security_password_is_empty)));
                    return;
                }
                if (TextUtils.isEmpty(newPassword)) {
                    postMainThread(() -> mView.showTip(App.sContext.getString(R.string.security_pwd_empty)));
                    return;
                }
                if (newPassword.length() != 8) {
                    postMainThread(() -> mView.showTip(App.sContext.getString(R.string.security_pwd_length_err)));
                    return;
                }
                //判断原安全密码是否正确
                if (!info.getSecurityPassword().equals(EncryptUtils.encryptSHA256ToString(oldPassword))) {
                    postMainThread(() -> mView.showTip(App.sContext.getString(R.string.org_security_password_err)));
                    return;
                }
                info.setSecurityPassword(EncryptUtils.encryptSHA256ToString(newPassword));
                break;
            default:
                break;
        }
        mRepository.setPasswordInfo(info);
        postMainThread(() -> mView.showSaveParamSuccessfully());
        postMainThread(() -> mView.showDetail());
    }

    /**
     * 保存参数到SP文件
     * 主要保存一些配置信息
     */
    private void doSaveParams() {
        String value;
        for (String key : mParamData.keySet()) {
            value = mParamData.get(key);
            //商户名称可为空，其它不可以
            if (!PreferencesConstants.MERCHANT_NAME.equals(key)) {
                if (TextUtils.isEmpty(value)) {
                    postMainThread(() -> mView.showTip(App.sContext.getString(R.string.parameter_empty)));
                    return;
                }
            }
            mLog.debug("key = {}, value = {}", key, value);
            switch (key) {
                case PreferencesConstants.MERCHANT_ID:
                    if (value.length() < 15) {
                        postMainThread(() -> mView.showTip(App.sContext.getString(R.string.merchant_number) + App.sContext.getString(R.string.parameter_error)));
                        return;
                    }
                    break;
                case PreferencesConstants.TERMINAL_ID:
                    if (value.length() < 8) {
                        postMainThread(() -> mView.showTip(App.sContext.getString(R.string.terminal_number) + App.sContext.getString(R.string.parameter_error)));
                        return;
                    }
                    break;
                case PreferencesConstants.ACQUIRING_NUMBER:
                    if (value.length() < 8) {
                        postMainThread(() -> mView.showTip(App.sContext.getString(R.string.acquiring_number) + App.sContext.getString(R.string.parameter_error)));
                        return;
                    }
                    break;
                case PreferencesConstants.PRINT_TIMES:
                    if (Integer.parseInt(value) == 0 || Integer.parseInt(value) > 3) {
                        postMainThread(() -> mView.showTip(App.sContext.getString(R.string.print_times) + App.sContext.getString(R.string.parameter_error)));
                        return;
                    }
                    break;
                case PreferencesConstants.TPDU:
                    if (value.length() < 10) {
                        postMainThread(() -> mView.showTip(App.sContext.getString(R.string.tpdu) + App.sContext.getString(R.string.parameter_error)));
                        return;
                    }
                    break;
                case PreferencesConstants.COMMUNICATION_TIMEOUT:
                    if (Integer.parseInt(value) < 15 || Integer.parseInt(value) > 60) {
                        postMainThread(() -> mView.showTip(App.sContext.getString(R.string.communication_timeout) + App.sContext.getString(R.string.parameter_error)));
                        return;
                    }
                    break;
                case PreferencesConstants.SERVER_IP:
                    if (!StringUtils.isIP(value)) {
                        postMainThread(() -> mView.showTip(App.sContext.getString(R.string.server_ip) + App.sContext.getString(R.string.parameter_error)));
                        return;
                    }
                    break;
                case PreferencesConstants.MASTER_KEY_INDEX:
                    if (Integer.parseInt(value) > 99) {
                        postMainThread(() -> mView.showTip(App.sContext.getString(R.string.master_key_index) + App.sContext.getString(R.string.parameter_error)));
                        return;
                    }
                    //主密钥索引有改动，设置为要重新签到
                    mRepository.setParamValue(PreferencesConstants.IS_NEED_LOGIN, "1");
                    break;
                default:
                    break;
            }
            mRepository.setParamValue(key, value);
        }
        mRepository.syncParamValue();
        mView.showSaveParamSuccessfully();
    }

    /**
     * 保存终端手输主密钥
     */
    private void saveMainKeyValue() {
        int keyIdx = 0;
        keyIdx = Integer.parseInt(StringUtils.firstNonEmpty(mParamData.get(PreferencesConstants.INPUT_MASTER_KEY_INDEX), "0"));
        if (keyIdx > 99) {
            postMainThread(() -> mView.showTip(App.sContext.getString(R.string.master_key_index) + App.sContext.getString(R.string.parameter_error)));
            return;
        }
        String value = mParamData.get(PreferencesConstants.INPUT_MASTER_KEY_VALUE);
        if (value.length() != 16 && value.length() != 32) {
            postMainThread(() -> mView.showTip(App.sContext.getString(R.string.master_key_value) + App.sContext.getString(R.string.parameter_error)));
            return;
        }
        //不保存到参数文件
        byte[] bValue = ByteUtils.hexString2ByteArray(value);
        PinPad sdkPinPad = ApiDeviceEngine.getInstance().getPinPad();
        //国密
        if ("2".equals(mRepository.getParamValue(PreferencesConstants.MASTER_KEY_ALGORITHM))) {
            sdkPinPad.setAlgorithmMode(AlgorithmModeEnum.SM4);
        }
        int result = sdkPinPad.writeMKey(keyIdx, bValue, bValue.length);
        if (result == SdkResult.Success) {
            //主密钥改变，要重新签到
            mRepository.setParamValue(PreferencesConstants.IS_NEED_LOGIN, "1");
            mRepository.syncParamValue();
            postMainThread(() -> mView.showSaveParamSuccessfully());
        } else {
            postMainThread(() -> mView.showTip(App.sContext.getString(R.string.master_key_value) + App.sContext.getString(R.string.setup_fail)));
        }
    }

    /**
     * 判断商户号及终端号的值是否变化了
     *
     * @return
     */
    private boolean judgeMerAndTerValueChanges() {
        //取出原商户号及终端号
        String orgMerId = mRepository.getParamValue(PreferencesConstants.MERCHANT_ID);
        String orgTerId = mRepository.getParamValue(PreferencesConstants.TERMINAL_ID);
        if (!TextUtils.isEmpty(orgMerId) && !TextUtils.isEmpty(orgTerId)) {
            if (!orgMerId.equals(mParamData.get(PreferencesConstants.MERCHANT_ID))) {
                return true;
            }
            if (!orgTerId.equals(mParamData.get(PreferencesConstants.TERMINAL_ID))) {
                return true;
            }
        }
        return false;
    }

    @RunOnMainThread
    private void postMainThread(Runnable runnable) {
        runnable.run();
    }
}
